home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
AdobeExamples
/
NX_CtlPoints
/
ControlView.m
< prev
next >
Wrap
Text File
|
1992-12-19
|
14KB
|
584 lines
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* ControlView.m
*
* Version: 2.0
* Author: Ken Fromm
* History:
* 03-07-91 Added this comment.
*/
#import "ControlPoint.h"
#import "ControlView.h"
#import "ControlViewWraps.h"
#import <appkit/Button.h>
#import <appkit/Control.h>
#import <appkit/Matrix.h>
#import <appkit/NXImage.h>
#import <appkit/TextField.h>
#import <dpsclient/wraps.h>
@implementation ControlView
- initFrame:(const NXRect *) frameRect
{
float ViewRect[4];
NXSize size;
[super initFrame:frameRect];
[self allocateGState];
NX_MALLOC(XYPoints, float, MAX_ARRAY);
NX_MALLOC(OpsBuffer, char, MAX_UPATHOPS);
NX_MALLOC(XYBuffer, float, (MAX_UPATHPTS));
ViewRect[0] = ViewRect[1] = 0.0;
ViewRect[2] = bounds.size.width;
ViewRect[3] = bounds.size.height;
PSWDefsView (BGCOLOR, BGCOLORSTR, BGWIDTHSTR, ViewRect);
srand(1);
indexOfPoints = 0;
size.width = size.height = FIGURESIZE;
imageId = [[[NXImage alloc] initSize:&size] setFlipped:NO];
[self makePoints:self];
return self;
}
/*
* Free the buffers
*/
- free
{
if (OpsBuffer)
NX_FREE(OpsBuffer);
if (XYPoints)
NX_FREE(XYPoints);
if (XYBuffer)
NX_FREE(XYBuffer);
return [super free];
}
/* The following methods are used to obtain the ids of the appropriate text fields. They
* were created by interface builder.
*/
-setDrawMethodsMatrix:anObject
{
drawMethodsMatrix = anObject;
return self;
}
-setDisplayTimesMatrix:anObject
{
displayTimesMatrix = anObject;
return self;
}
-setNumberPointsMatrix:anObject
{
numberPointsMatrix = anObject;
numberOfPoints = [numberPointsMatrix selectedTag];
return self;
}
-setControlPoint:anObject
{
controlPoint = anObject;
return self;
}
-setButtonTitle:(OP) title
{
if (title == FILL)
{
[[drawMethodsMatrix cellAt:2 :0] setTitle:"ufill"];
[[drawMethodsMatrix cellAt:3 :0]setTitle:"rectfill"];
}
else
{
[[drawMethodsMatrix cellAt:2 :0] setTitle:"ustroke"];
[[drawMethodsMatrix cellAt:3 :0]setTitle:"rectstroke"];
}
return self;
}
-setButtonEnable:(BOOL) enable
{
[[drawMethodsMatrix cellAt:3 :0] setEnabled:enable];
return self;
}
-psTrace:sender
{
if (PSTrace == NO)
[[sender selectedCell] setTitle:"Trace On"];
else
[[sender selectedCell] setTitle:"Trace Off"];
PSTrace = !PSTrace;
return self;
}
-configureDependence:sender
{
[controlPoint deviceDependence:[sender state]];
[self eraseTimes:self];
return self;
}
-configurePoints:sender
{
numberOfPoints = [numberPointsMatrix selectedTag];
/* Choose a new starting index to instill a little change in the display. */
indexOfPoints = (rand () % (MAX_POINTS - numberOfPoints + 1)) * 2;
[self eraseTimes:self];
return self;
}
/*
* This method fills up the array of points randomly. If the number of points to draw
* is different from the previous time, then a new place in the array will be selected for the
* points (except for the case of the largest number of points, in this instance the 0 index will
* be used). This random selection of indices introduces a little bit of change in the display.
*/
-makePoints:sender
{
int i;
for (i = 0; i < MAX_ARRAY; i = i +2)
{
XYPoints[i] = (rand () % (long)((bounds.size.width -8) * 100) + 400) * 0.01;
XYPoints[i+1] = (rand () % (long)((bounds.size.height -8) * 100) + 400) * 0.01;
}
return self;
}
-eraseTimes:sender
{
int i;
for (i = 0; i < [displayTimesMatrix cellCount]; i++)
[[displayTimesMatrix cellAt:i :0] setStringValue:""];
return self;
}
/* Draw using the method selected. */
-drawViewOne:sender
{
int i, row;
row = [sender selectedRow];
drawFlags.field = 0x80 >> row;
[self display];
return self;
}
/* Draw using all the methods. */
-drawViewAll:sender
{
drawFlags.field = DRAWALL;
[self display];
return self;
}
/*
* Below are six methods that use different approaches to drawing control points.
*/
/* The drawing will center around the point passed in.*/
-drawBasic:(int) cell
{
int ElapsedTime, i;
char *basicProc, *basicOp;
basicProc = [controlPoint getBasicProc];
basicOp = [controlPoint getBasicOp];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSWEraseView();
PSsetlinewidth(0.15);
PSWMarkTime(); NXPing();
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
PSWBasic(XYPoints[i], XYPoints[i+1], basicProc, basicOp);
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/*
* Cache a single user path. Translate to each location and then
* image the user path.
*/
-drawUserCache:(int) cell
{
int ElapsedTime, i, i_pt, i_op, j;
char *userOp, *userOpsArray;
float *userPtsArray;
userPtsArray = [controlPoint getUserPtsArray];
userOpsArray = [controlPoint getUserOpsArray];
userOp = [controlPoint getUserOp];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSWEraseView();
PSsetlinewidth(0.15);
PSWMarkTime (); NXPing();
/*
* Places a user path description for a generic control
* point into the OpsBuffer and XYBuffer.
*/
i_op = i_pt = 0;
OpsBuffer[i_op++] = dps_ucache;
/* The bounding box is the size of the control point. */
XYBuffer[i_pt++] = -FIGURESIZE/2;
XYBuffer[i_pt++] = -FIGURESIZE/2;
XYBuffer[i_pt++] = FIGURESIZE/2;
XYBuffer[i_pt++] = FIGURESIZE/2;
OpsBuffer[i_op++] = dps_setbbox;
XYBuffer[i_pt++] = 0;
XYBuffer[i_pt++] = 0;
OpsBuffer[i_op++] = dps_moveto;
for (j = 1; j <= userPtsArray[0]; j++)
XYBuffer[i_pt++] = userPtsArray[j];
for (j = 1; j <= (int) userOpsArray[0]; j++)
OpsBuffer[i_op++] = userOpsArray[j];
/*
* Performs an initial translate to the first location
* and then performs a relative translation thereafter.
*/
PSgsave();
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
PStranslate(XYPoints[indexOfPoints], XYPoints[indexOfPoints+1]);
for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
{
PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
PStranslate(XYPoints[i+2] - XYPoints[i], XYPoints[i+3] - XYPoints[i+1]);
}
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSgrestore();
PSWReturnTime (&ElapsedTime);
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/* Represents the control points as a large user path comprised of a set of sub user paths. */
-drawUserPath:(int) cell
{
int ElapsedTime, i, i_pt, i_op, j;
char *userOp, *userOpsArray;
float *userPtsArray;
userPtsArray = [controlPoint getUserPtsArray];
userOpsArray = [controlPoint getUserOpsArray];
userOp = [controlPoint getUserOp];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSWEraseView();
PSsetlinewidth(0);
PSWMarkTime (); NXPing();
/* Place the bounding box in the user path description. */
XYBuffer[0] = bounds.origin.x;
XYBuffer[1] = bounds.origin.y;
XYBuffer[2] = bounds.origin.x + bounds.size.width;
XYBuffer[3] = bounds.origin.y + bounds.size.height;
OpsBuffer[0] = dps_setbbox;
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
i = 0; i_pt = 4; i_op = 1;
while (i < numberOfPoints * 2)
{
/*
* This check sends the array to the server if the array
* limit has been reached.
*/
if ((i_pt + userPtsArray[0] > MAX_UPATHPTS) ||
(i_op + (int) userOpsArray[0] > MAX_UPATHOPS))
{
PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
i_pt = 4; i_op = 1;
}
XYBuffer[i_pt++] = XYPoints[indexOfPoints + i++];
XYBuffer[i_pt++] = XYPoints[indexOfPoints + i++];
OpsBuffer[i_op++] = dps_moveto;
for (j = 1; j <= userPtsArray[0]; j++, i_pt++)
XYBuffer[i_pt] = userPtsArray[j];
for (j = 1; j <= (int) userOpsArray[0]; j++, i_op++)
OpsBuffer[i_op] = userOpsArray[j];
}
PSWUserPath(XYBuffer, i_pt, OpsBuffer, i_op, userOp);
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/*
* Here we have to calculate the offset from the center because
* rectfill starts drawing at the location passed in.
*/
-drawRectOp:(int) cell
{
int ElapsedTime, i, j;
char *rectOp;
rectOp = [controlPoint getRectOp];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSWEraseView();
PSsetlinewidth(0);
PSWMarkTime (); NXPing();
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
/* Draw the rectangles if the array limit has been reached. */
for (i = indexOfPoints, j = 0; i < indexOfPoints + (numberOfPoints*2); i = i+2, j = j+4)
{
/* Flush the buffer if full. */
if (j+3 > MAX_RECTPTS)
{
PSWRectDraw (XYBuffer, j, rectOp);
j = 0;
}
XYBuffer[j] = XYPoints[i] - RECTOFFSET;
XYBuffer[j+1] = XYPoints[i+1] - RECTOFFSET;
XYBuffer[j+2] = RECTSIZE;
XYBuffer[j+3] = RECTSIZE;
}
PSWRectDraw (XYBuffer, j, rectOp);
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/*
* Draws the control point into the NXImage and then composites it at each
* control point location.
*/
-drawComposite:(int) cell
{
int ElapsedTime, i;
NXPoint point;
[controlPoint drawImage:imageId];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSWEraseView();
PSWMarkTime (); NXPing();
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
/* The adjustment centers the rectangle on the point location. */
for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
{
point.x = XYPoints[i] - FIGUREHALFSIZE;
point.y = XYPoints[i+1] - FIGUREHALFSIZE;
[imageId composite:NX_SOVER toPoint:&point];
}
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/*
* Performs a moveto show for each control point.
*/
-drawShow:(int) cell
{
int ElapsedTime, i;
char fontchar[2];
fontchar[0] = [controlPoint getChar];
fontchar[1] = 0;
[controlPoint selectFont:FONTSIZE];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSgsave();
PSWEraseView();
PSWMarkTime (); NXPing();
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
for (i = indexOfPoints; i < indexOfPoints + (numberOfPoints*2); i = i+2)
PSWShow(XYPoints[i], XYPoints[i+1], fontchar);
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSgrestore();
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/*
* Places the characters and relative offsets into arrays and executes
* a single xyshow.
*/
-drawXYShow:(int) cell
{
int ElapsedTime, i, j;
char fontchar;
fontchar = [controlPoint getChar];
/*
* Place the characters into the character string for xyshow.
* Terminate the string with a NULL character.
*/
for (i = 0; i < numberOfPoints; i++)
OpsBuffer[i] = fontchar;
OpsBuffer[i] = 0;
[controlPoint selectFont:FONTSIZE];
[[displayTimesMatrix cellAt:cell :0] setStringValue:""];
PSgsave();
PSWEraseView();
PSWMarkTime (); NXPing();
/* Calculate the displacement from the previous character. */
for (i = indexOfPoints+2, j = 0; i < indexOfPoints + (numberOfPoints*2); i++, j++)
XYBuffer[j] = XYPoints[i] - XYPoints[i-2];
/*
* Provide a dummy set of displacements for the move after
* the last character has been shown.
*/
XYBuffer[j++] = 0;
XYBuffer[j++] = 0;
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), YES);
/* Establish a current point and then execute the xyshow. */
PSWXYShow(XYPoints[indexOfPoints], XYPoints[indexOfPoints+1],
OpsBuffer, XYBuffer, j);
if (PSTrace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSgrestore();
[[displayTimesMatrix cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/* Messaged by the "display" method. This method should not be called directly. */
-drawSelf:(NXRect *)r :(int) count
{
PSWEraseView();
PSsetgray(NX_BLACK);
if (drawFlags.flags.basic)
[self drawBasic:0];
if (drawFlags.flags.usercache)
[self drawUserCache:1];
if (drawFlags.flags.userpath)
[self drawUserPath:2];
if (drawFlags.flags.rectop && [[drawMethodsMatrix cellAt:3 :0] isEnabled])
[self drawRectOp:3];
if (drawFlags.flags.composite)
[self drawComposite:4];
if (drawFlags.flags.show)
[self drawShow:5];
if (drawFlags.flags.xyshow)
[self drawXYShow:6];
return self;
}
@end